home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
assemblr
/
library
/
edit
/
fremacsr
/
redisp.asm
< prev
next >
Wrap
Assembly Source File
|
1987-02-15
|
37KB
|
1,619 lines
;History:457,1
.xlist
HT equ 09h
LF equ 0ah
CR equ 0dh
LINENEW equ CR+LF*256 ;the way a newline is stored in memory.
TRAIL_BLANK equ 4dh
TRAIL_TAB equ 4eh
MORE_CHAR equ 52h
NEWLINE_CHAR equ 54h
bufseg segment byte public
extrn toptop: word
extrn topbot: word
extrn bottop: word
extrn botbot: word
extrn linecount: word
extrn linesbefore: word
public memsize
memsize dw ?
bufseg ends
data segment byte public
if 1
public w1, w2, this_point, this_row, other_row, topbotpercent
public botpercent, toppercent, firstlimit, lastlimit, overwrite_row
public overwrite_col, screen_column, window, inversed, inverse_mark
public showblanks
endif
;pointrow contains the row that the cursor is currently on, relative to the
; screen boundaries. Pointrow may be negative if the point is above the screen,
; or it may be larger than max_screen_line if the point is below the screen.
wind_struc struc
windseg dw ?
pointrow dw ?
firstline db ?
lastline db ?
firstpossible db ?
lastpossible db ?
firstcolumn dw ?
wind_struc ends
w1 wind_struc<>
w2 wind_struc<>
this_point dw ? ;->point in the current file.
this_row dw ? ;row of point on screen.
other_row dw ? ;row of point in other window.
topbotpercent label word
botpercent db ?
toppercent db ?
firstlastlimits label word
firstlimit db ?
lastlimit db ?
public next_redisp_line
next_redisp_line dw 0
public overwrite_flag
overwrite_flag db 0 ;=0 if not overwriting.
overwrite_rowcol label word
overwrite_row db 0
overwrite_col db 0
;the following externs are in the computer-dependent file
extrn max_screen_line: byte
;the following externs are in 'buffers'
extrn textseg: word
screen_column dw ?
;window contains a list of which lines should be moved where, and which
; lines need to be redrawn. If an entry is positive, then the line which is
; currently at x belongs at window[x]. If an entry is TRASHED, it
; should be redrawn.
;inversed contains a list of which lines currently show inverse video.
window db 50 dup(?) ;50 is > max_screen_line
inversed db 50 dup(?) ;. .
public inversing
inversing dw 0
inverse_mark dw ?
public inverse_flag
inverse_flag db 0 ;=0 means no inversing.
TRASHED equ -1 ;note that TRASHED must be negative.
showblanks db 0
data ends
b_struc struc
b db ?
b_struc ends
w_struc struc
w dw ?
w_struc ends
byte_ptr label byte
code segment byte public
;all the routines in this segment are entered with ds=data, es=data
assume cs:code, ds:data, es:data
;the following externs are in the computer-dependent file.
extrn move_line: near
extrn clear_to_eol: near
extrn xychrout: near
extrn hardware_roll_up: near
extrn hardware_roll_down: near
extrn position_cursor: near
extrn xyputch: near
;the following externs are in 'memory'
extrn compute_cursor$: near
extrn set_line$: near
;the following externs are in 'buffers'
extrn succ_buffer: near
extrn buffer_number: near
;enter with bx=paragraph of buffer.
;exit with ax=number of buffer.
extrn buffer_allocate: near
extrn find_buffer: near
;enter with cx=buffer number.
;exit with nc, dx set to that buffer if it exists, cy otherwise.
;the following externs are in 'marks'
extrn read_mark$: near
extrn goto_mark$: near
extrn get_split_mark: near
extrn get_mark: near
extrn split_at_point: near
extrn set_mark_si: near
extrn set_mark: near
extrn stack_marks: near
extrn goto_mark: near
public read_panes
read_panes:
ret
public read_current_window
read_current_window:
mov ax,1 ;probably window 1.
cmp w2.windseg,0 ;no window 2 - must be 1.
je read_current_window_1
mov bl,w1.firstline
cmp bl,w2.firstline
jb read_current_window_1
inc ax
read_current_window_1:
ret
public store_current_window
store_current_window:
cmp ax,1
jne store_current_window_1
cmp w2.windseg,0 ;is there a second window?
je store_current_window_2 ;no - don't swap.
mov al,w1.firstline
cmp al,w2.firstline
jb store_current_window_2
call swap_other_row
call swap_windows
jmp short store_current_window_2
store_current_window_1:
cmp ax,2
jne store_current_window_2
cmp w2.windseg,0 ;is there a second window?
je store_current_window_2 ;no - don't swap.
mov al,w1.firstline
cmp al,w2.firstline
ja store_current_window_2
call swap_other_row
call swap_windows
store_current_window_2:
ret
swap_other_row:
mov ax,w1.windseg ;are we in the other window?
cmp ax,w2.windseg
jne swap_other_row_1 ;no - no worries.
push w1.pointrow ;remember what other_row will be.
mov ax,1
call stack_marks
mov ax,'*'*256+'0' ;0 := *
call set_mark
mov ax,'.'*256+'*' ;* := .
call set_mark
mov al,'0' ;. := 0
call goto_mark
mov ax,0
call stack_marks
pop other_row
swap_other_row_1:
ret
public read_other_window
read_other_window:
mov bx,w2.windseg
or bx,bx
je read_other_window_1
call buffer_number
ret
read_other_window_1:
xor ax,ax
ret
public store_other_window
store_other_window:
;enter with ax=buffer segment to show.
mov cx,ax ;do they want one window?
jcxz store_other_window_3 ;yes.
call find_buffer ;find the buffer.
jc store_other_window_3 ;can't find it - give them one window.
cmp w2.windseg,0 ;do we have another window to set?
jne store_other_window_1 ;yes - just set it.
push dx
call split_screen
pop dx
store_other_window_1:
cmp dx,w2.windseg ;is it already showing?
je store_other_window_2 ;yes - they're being silly.
mov w2.windseg,dx ;show the buffer here.
cmp w1.windseg,dx ;is this buffer also in w1?
jne store_other_window_4 ;no - no worries.
mov ax,w1.pointrow ;the place that the this window is at
mov other_row,ax ; becomes the other row.
mov ax,'.'*256+'*' ;set the split mark to the point.
call set_mark
store_other_window_4:
mov bl,w2.firstline ;trash what's there.
mov al,w2.lastline
call trash_some_lines
store_other_window_2:
ret
store_other_window_3:
mov w2.windseg,0
mov al,max_screen_line ;fill the screen with this window.
mov w1.lastline,al
mov w1.firstline,0
mov si,offset w1
call set_window_percent
call paint_screen
ret
split_screen:
mov al,max_screen_line
mov w2.lastline,al
sar al,1
dec al
mov w1.lastline,al
add al,2
mov w2.firstline,al
mov si,offset w1
call set_window_percent
mov si,offset w2
call set_window_percent
call paint_screen
ret
public store_panes
store_panes:
ret
public store_showblanks
store_showblanks:
cmp showblanks,al ;are we changing it?
mov showblanks,al ;store it in any case.
je store_showblanks_1 ;if we changed it, paint the window.
call paint_window
store_showblanks_1:
ret
public read_showblanks
read_showblanks:
mov al,showblanks
ret
public read_firstline
read_firstline:
mov al,w1.firstline
ret
public read_lastline
read_lastline:
mov al,w1.lastline
ret
public read_newrow
read_newrow:
mov ax,w1.pointrow
ret
public read_firstcolumn
read_firstcolumn:
mov ax,w1.firstcolumn
ret
public read_top_percent
read_top_percent:
mov al,toppercent
ret
public read_bot_percent
read_bot_percent:
mov al,botpercent
ret
public store_top_percent
store_top_percent:
mov toppercent,al
mov si,offset w1
call set_window_percent
ret
public store_bot_percent
store_bot_percent:
mov botpercent,al
mov si,offset w1
call set_window_percent
ret
public init_screen
init_screen:
xor al,al
mov w1.firstline,al
mov w1.firstpossible,al
mov al,max_screen_line ;fill the screen with this window.
mov w1.lastline,al
mov w1.lastpossible,al
mov w1.firstcolumn,0
mov ax,textseg
mov w1.windseg,ax
ret
public gotoxy
gotoxy:
cmp dl,max_screen_line ;is max_screen_line ok?
jbe gotoxy_1 ;yes.
mov dl,max_screen_line ;no - take min(dl, max_screen_line)
gotoxy_1:
cmp dh,79 ;are we on the screen?
jbe gotoxy_2
mov dh,79 ;no - take min(dh, 79)
gotoxy_2:
mov overwrite_rowcol,dx
ret
public chrout
chrout:
;enter with ax=char to "type" on screen.
;preserve si.
cmp overwrite_flag,0 ;are we already overwriting?
jne chrout_1 ;yes.
mov overwrite_flag,1 ;say that we're overwriting
mov window[0],TRASHED ;trash the first line.
chrout_1:
mov dx,overwrite_rowcol ;get the cursor position.
cmp al,CR ;go to left margin?
jne chrout_4
call clear_to_eol ;yes - clear to end here.
mov dh,0
jmp chrout_exit
chrout_4:
cmp al,LF ;go down a line?
jne chrout_5
inc dl
cmp dl,max_screen_line ;are we past the last line?
jbe chrout_exit ;no.
call hardware_roll_up ;yes - roll the screen up.
jnc chrout_6
mov dl,1 ;have to software scroll.
chrout_7:
mov al,dl
dec al
call move_line
inc dl
cmp dl,max_screen_line
jbe chrout_7
chrout_6:
mov dl,max_screen_line ;say on the last line.
push dx ;clear the entire line.
mov dh,0
call clear_to_eol
pop dx
jmp short chrout_exit
chrout_5:
cmp al,HT
jne chrout_8
chrout_9:
mov ah,0
mov al,' '
call chrout_putch
test dh,7
jnz chrout_9
jmp short chrout_exit
chrout_8:
call chrout_putch
chrout_exit:
mov overwrite_rowcol,dx ;remember where we are.
call position_cursor
ret
chrout_putch:
mov bh,0 ;trash the line.
mov bl,dl
mov window[bx],TRASHED
call xyputch
inc dh
ret
public redisplay
redisplay:
mov ax,textseg ;is the current buffer showing in w1?
cmp ax,w1.windseg
je redisplay$_1 ;yes - all ok.
xchg w1.windseg,ax ;no - put it in this window.
cmp ax,w2.windseg ;was the old w1 showing in w2?
jne redisplay$_2 ;no - nothing special.
push ds
mov ds,w2.windseg
mov al,'*' ;yes - make the split mark the point
call goto_mark$
pop ds
redisplay$_2:
mov bl,w1.firstline
mov al,w1.lastline
call trash_some_lines
mov ax,w1.windseg ;is this buffer also in w2?
cmp ax,w2.windseg
jne redisplay$_1 ;no - no worries.
mov bl,w2.firstline ;yes - trash one line so that
mov bh,0 ; the point is recomputed. hack, hack.
mov window[bx],TRASHED
mov ax,w2.pointrow ;the place that the other window is at
mov other_row,ax ; becomes the other row.
mov ax,'.'*256+'*' ;set the split mark to the point.
call set_mark
redisplay$_1:
mov overwrite_flag,0 ;no longer overwriting.
mov dx,0 ;start in the upper left hand corner
mov overwrite_rowcol,dx ; the next time we overwrite.
if 0
mov dx,0*256+24 ;dh=column, dl=row.
mov si,offset window
rd_0:
lodsb
add al,'A'
call xychrout
inc dh
cmp dh,25
jb rd_0
mov si,offset inversed
rd_1:
lodsb
add al,'0'
call xychrout
inc dh
cmp dh,48
jb rd_1
endif
push ds
mov ds,w1.windseg
assume ds:bufseg
mov si,topbot
mov this_point,si
mov ax,next_redisp_line
call force_point_into_window
mov ax,w1.pointrow
mov this_row,ax
call redraw_trashed
mov ax,this_row
mov w1.pointrow,ax
pop ds
assume ds:data
mov dx,screen_column
sub dx,w1.firstcolumn
mov dh,dl
mov dl,byte ptr w1.pointrow
call position_cursor
cmp w2.windseg,0 ;is there a second window?
je redisplay_one ;no.
call swap_windows
push ds
mov ax,w1.windseg ;are they the same file?
cmp ax,w2.windseg
mov ds,ax ;really w2.
assume ds:bufseg
jne redisplay__2
;two windows into the same buffer.
call get_split_mark ;get the split mark.
cmp si,bottop ;are we at the point?
jne redisplay__1 ;no.
mov si,topbot ;yes - always use the top point.
redisplay__1:
mov this_point,si
mov ax,other_row ;get the row in the other window.
mov this_row,ax
call redraw_trashed
mov ax,this_row
xchg other_row,ax
sub ax,other_row ;how much did we adjust it by?
sub w1.pointrow,ax ;adjust pointrow, too.
jmp short redisplay__3
redisplay__2:
;two windows, two buffers.
mov si,topbot
mov this_point,si
xor ax,ax
call force_point_into_window
mov ax,w1.pointrow
mov this_row,ax
call redraw_trashed
redisplay__3:
call swap_windows
pop ds
assume ds:data
redisplay_one:
mov next_redisp_line,0 ;no more desired line
ret
code ends
code segment byte public
;all the code in this segment is entered with ds=bufseg, es=data
assume cs:code, ds:bufseg, es:data
public adjust_buffers
adjust_buffers:
;enter with ds,bx=old buffer paragraph, ax=new buffer paragraph.
;exit with all registers undisturbed!
cmp w1.windseg,bx ;are we changing w1?
jne adjust_buffers_1
mov w1.windseg,ax
adjust_buffers_1:
cmp w2.windseg,bx ;are we changing w2?
jne adjust_buffers_2
mov w2.windseg,ax
adjust_buffers_2:
ret
set_window_percent:
;note that set_window_percent doesn't use ds.
;enter with si->window to set.
mov cl,100
mov ch,data:[si].lastline
sub ch,data:[si].firstline
inc ch
mov al,toppercent
mul ch
div cl
cmp al,ch
jb set_window_percent_1
xor al,al
set_window_percent_1:
add al,data:[si].firstline
mov data:[si].firstpossible,al
mov al,botpercent
mul ch
div cl
mov ch,data:[si].lastline
sub ch,al
jae set_window_percent_2
mov ch,data:[si].lastline
set_window_percent_2:
mov data:[si].lastpossible,ch
ret
roll_window_down_2_j_1:
jmp roll_window_down_2
roll_window_down_5_j_1:
jmp roll_window_down_5
roll_window_down:
;roll the window down until pointrow is in the window.
mov al,firstlimit
cbw
cmp w1.pointrow,ax ;if pointrow>=firstlimit, we don't
jge roll_window_down_2_j_1 ; need to roll down.
;Are there any lines now on the screen that will remain? Go if not.
mov cx,w1.pointrow
mov bh,0
mov bl,w1.lastline
add cx,bx
mov bl,w1.firstline
sub cx,bx
mov bl,firstlimit
cmp cx,bx
jl roll_window_down_5_j_1 ;we have to repaint the entire window.
mov dx,w1.pointrow
mov cl,w1.firstline
mov ch,0
sub dx,cx
inc dx
;now compute the number of times we need to roll.
mov cx,w1.pointrow
sub cx,bx
mov w1.pointrow,bx ;bx is firstlimit
neg cx
;Can we use the hardware scroll? Go if not.
cmp w1.firstline,0
jne roll_window_down_3
mov al,max_screen_line
cmp w1.lastline,al
jne roll_window_down_3
;Use the hardware scroll unless there isn't one.
xchg cx,dx ;get the distance to skip
call skip_to_line
mov cx,dx
roll_window_down_4:
call hardware_roll_down
jc roll_window_down_3 ;can't hardware roll.
;now adjust window[] for the change we just made to the screen.
mov bl,w1.firstline
mov bh,0
mov al,window[bx] ;save the current values for later.
mov ah,inversed[bx]
push ax
push si
call redraw_compare ;remember if we're inversing here.
mov inversed[bx],al
call redraw_line
call remember_redrawn
pop si
call prevline
mov window[bx],bl ;remember that this line is real.
pop ax ;restore the old values.
roll_window_down_6:
cmp al,TRASHED ;is this a trashed line?
je roll_window_down_7
inc al ;no - say that the line's moved up.
cmp al,max_screen_line ;did it roll off the screen?
jbe roll_window_down_7 ;no.
mov al,TRASHED ;yes - it's gone.
roll_window_down_7:
inc bl
xchg al,window[bx]
xchg ah,inversed[bx]
cmp bl,w1.lastline
jb roll_window_down_6
loop roll_window_down_4
jmp short roll_window_down_2
;repaint screen.
roll_window_down_5:
call center_this
jmp short roll_window_down_2
;Use software scroll. All we do is roll the window array.
roll_window_down_3:
mov bl,w1.firstline
mov bh,0
mov al,window[bx] ;save the current value for later.
mov ah,inversed[bx]
mov window[bx],TRASHED
roll_window_down_1:
inc bl
xchg al,window[bx]
xchg ah,inversed[bx]
cmp bl,w1.lastline
jb roll_window_down_1
loop roll_window_down_3
roll_window_down_2:
ret
roll_window_up_2_j_1:
jmp roll_window_up_2
roll_window_up:
mov al,lastlimit
cbw
cmp w1.pointrow,ax ;if pointrow<=lastlimit, we don't
jle roll_window_up_2_j_1 ; need to roll up.
;compute: pointrow-(lastline-firstline) > lastlimit
;Are there any lines now on the screen that will remain? Go if not.
mov cx,w1.pointrow
mov bh,0
mov bl,w1.firstline
add cx,bx
mov bl,w1.lastline
sub cx,bx
mov bl,lastlimit
cmp cx,bx
jg roll_window_up_5 ;we have to repaint the entire window.
mov dx,w1.pointrow
mov cl,w1.lastline
mov ch,0
sub dx,cx
dec dx
;now compute the number of times we need to roll.
mov cx,w1.pointrow
sub cx,bx
mov w1.pointrow,bx ;bx is lastlimit.
;Can we use hardware scroll? Go if not.
cmp w1.firstline,0
jne roll_window_up_3
mov al,max_screen_line
cmp w1.lastline,al
jne roll_window_up_3
;Use the hardware scroll unless there isn't one.
xchg cx,dx ;get the distance to skip
call skip_to_line
mov cx,dx
roll_window_up_4:
call hardware_roll_up
jc roll_window_up_3 ;can't hardware roll.
;now adjust window[] for the change we just made to the screen.
mov bl,w1.lastline
mov bh,0
mov al,window[bx] ;save the current values for later.
mov ah,inversed[bx]
push ax
call redraw_compare ;remember if we're inversing here.
mov inversed[bx],al
call redraw_line
call remember_redrawn
mov window[bx],bl ;remember that this line is real.
pop ax ;restore old values.
roll_window_up_6:
cmp al,TRASHED ;has this line been trashed?
je roll_window_up_7
dec al ;no - say the line's been moved.
roll_window_up_7:
dec bl
xchg al,window[bx]
xchg ah,inversed[bx]
cmp bl,w1.firstline
ja roll_window_up_6
loop roll_window_up_4
jmp short roll_window_up_2
;repaint screen.
roll_window_up_5:
call center_this
jmp short roll_window_up_2
;Use software scroll. All we do is roll the window array.
roll_window_up_3:
mov bl,w1.lastline
mov bh,0
mov al,window[bx] ;save the current value for later.
mov ah,inversed[bx]
mov window[bx],TRASHED
roll_window_up_1:
dec bl
xchg al,window[bx]
xchg ah,inversed[bx]
cmp bl,w1.firstline
ja roll_window_up_1
loop roll_window_up_3
roll_window_up_2:
ret
;enter with pointrow=current relative screen line
;exit with a line inserted before pointrow.
public window_insert
window_insert:
push si
mov ax,ds ;is this in window 1?
cmp ax,w1.windseg
jne window_insert_1
mov si,offset w1
call window_ins
window_insert_1:
mov ax,ds ;is this in window 2?
cmp ax,w2.windseg
jne window_insert_2
mov si,offset w2
call window_ins
window_insert_2:
mov ax,ds ;are we showing in both windows?
cmp ax,w1.windseg
jne window_insert_3
cmp ax,w2.windseg
jne window_insert_3
call split_at_point ;is the split mark at or after the point?
jnc window_insert_3 ;no
inc other_row ;yes - must increment the other row.
window_insert_3:
pop si
ret
;private subroutine, called by window_insert to insert a line in a window.
;enter with si-> a window structure.
window_ins:
mov bx,data:[si].pointrow
mov al,data:[si].firstline
cbw
cmp bx,ax ;are we above the screen?
jl window_ins_3 ;yes - exit.
mov al,data:[si].lastline
cmp bx,ax ;are we below the screen?
jg window_ins_2 ;yes - go down a row.
mov window[bx],TRASHED
mov al,TRASHED
jmp short window_ins_4
window_ins_1:
xchg al,window[bx]
xchg ah,inversed[bx]
window_ins_4:
inc bl
cmp bl,data:[si].lastline
jbe window_ins_1
window_ins_2:
inc data:[si].pointrow
window_ins_3:
ret
;enter with pointrow=current relative screen line
;exit with the line at pointrow deleted.
public window_delete
window_delete:
push si
mov ax,ds ;is this in window 1?
cmp ax,w1.windseg
jne window_delete_1
mov si,offset w1
call window_del
window_delete_1:
mov ax,ds ;is this in window 2?
cmp ax,w2.windseg
jne window_delete_2
mov si,offset w2
call window_del
window_delete_2:
mov ax,ds ;are we showing in both windows?
cmp ax,w1.windseg
jne window_delete_3
cmp ax,w2.windseg
jne window_delete_3
call split_at_point ;is the split mark at or after the point?
jnc window_delete_3 ;no
dec other_row ;yes - must decrement the other row.
window_delete_3:
pop si
ret
;private subroutine, called by window_delete to delete a line from a window.
;enter with si-> a window structure.
window_del:
mov bx,data:[si].pointrow
mov al,data:[si].firstline
cbw
cmp bx,ax ;are we above the screen?
jl window_del_4 ;yes.
mov al,data:[si].lastline
cbw
cmp bx,ax ;are we below the screen?
jg window_del_1 ;yes.
mov window[bx],TRASHED ;kill the line the cursor is on.
jmp short window_del_5 ;go into while...do loop
window_del_4:
inc data:[si].pointrow
jmp short window_del_1
window_del_3:
mov al,window[bx+1]
mov ah,inversed[bx+1]
mov window[bx],al
mov inversed[bx],ah
window_del_5:
inc bl
cmp bl,data:[si].lastline
jb window_del_3
mov window[bx],TRASHED ;kill lastline
window_del_1:
ret
public trash_line
trash_line:
;destroy the line that the point is on if it's also in the window.
mov ax,ds ;is this in window 1?
cmp ax,w1.windseg
jne trash_line_1
mov si,offset w1
call trash_line_0
trash_line_1:
mov ax,ds ;is this in window 2?
cmp ax,w2.windseg
jne trash_line_2
mov si,offset w2
call trash_line_0
trash_line_2:
ret
;enter with si-> a window structure.
trash_line_0:
mov bx,data:[si].pointrow
mov al,data:[si].firstline
cbw
cmp bx,ax
jl trash_line_3
mov al,data:[si].lastline
cbw
cmp bx,ax
jg trash_line_3
mov window[bx],TRASHED
trash_line_3:
ret
public up_lines
up_lines:
mov ax,ds ;is this in window 2?
cmp ax,w1.windseg
jne up_lines_1
sub w1.pointrow,bx
up_lines_1:
mov ax,ds ;is this in window 2?
cmp ax,w2.windseg
jne up_lines_2
sub w2.pointrow,bx
up_lines_2:
ret
public down_lines
down_lines:
mov ax,ds ;is this in window 1?
cmp ax,w1.windseg
jne down_lines_1
add w1.pointrow,bx
down_lines_1:
mov ax,ds ;is this in window 2?
cmp ax,w2.windseg
jne down_lines_2
add w2.pointrow,bx
down_lines_2:
ret
public paint_screen
paint_screen:
;note that paint doesn't use ds.
;what's on the screen is garbage.
;preserve si, dx.
mov bl,0
mov al,max_screen_line
call trash_some_lines
ret
center_window:
;note that center doesn't use ds.
;preserve dx.
center_this:
mov cl,w1.lastline ;compute the middle of the screen.
sub cl,w1.firstline
sar cl,1
add cl,w1.firstline
mov ch,0
mov w1.pointrow,cx
mov bl,w1.firstline
mov al,w1.lastline
call trash_some_lines
ret
public paint_window
paint_window:
;preserve dx.
mov ax,textseg
cmp ax,w1.windseg
jne paint_window_1
mov bl,w1.firstline
mov al,w1.lastline
call trash_some_lines
paint_window_1:
mov ax,textseg
cmp ax,w2.windseg
jne paint_window_2
mov bl,w2.firstline
mov al,w2.lastline
call trash_some_lines
paint_window_2:
ret
trash_some_lines:
;enter with bl=first line to destroy, al=last line.
;preserve si, dx.
mov w1.firstcolumn,0 ;go to the first column.
mov bh,0
trash_some_lines_0:
mov window[bx],TRASHED
inc bl
cmp bl,al
jbe trash_some_lines_0
mov al,w1.firstpossible ;ensure that we're not above the screen.
cbw
cmp w1.pointrow,ax
jge trash_some_lines_1 ;we're not.
mov w1.pointrow,ax
trash_some_lines_1:
mov al,w1.lastpossible ;ensure that we're not below the screen.
cbw
cmp w1.pointrow,ax
jle trash_some_lines_2 ;we're not.
mov w1.pointrow,ax
trash_some_lines_2:
ret
;swap the two window data structures.
swap_windows:
mov si,offset w1
mov di,offset w2
mov cx,(size wind_struc)
swap_windows_0:
mov al,data:[si]
xchg al,data:[di]
mov data:[si],al
inc si
inc di
loop swap_windows_0
ret
force_point_into_window:
;enter with al=the desired row, =0 if we don't care.
comment /**********************************************************************
* roll the window array until pointrow is on the screen.
* when we roll the array, the lines we roll in must be repainted.
* for example, assume: screen is 0..23
* if pointrow is 5, then we're done.
* if pointrow is -7, then we must roll down 7 lines.
* if pointrow is <=-24, then we must roll down 24 lines, which says that the
* entire screen will be repainted.
* if pointrow is 27, then we must roll up 3 lines.
* if pointrow is >=48, then we must roll up 24 lines, which says that the
* entire screen will be repainted.
*****************************************************************************/
mov bl,w1.firstpossible
mov bh,w1.lastpossible
or al,al ;do we have a desired row?
je redisplay_1 ;no.
dec al
cmp al,bl ;above firstpossible?
ja redisplay_0 ;yes - ok.
mov al,bl ;no - clip to firstpossible.
redisplay_0:
cmp al,bh ;below lastpossible?
jb redisplay_00 ;yes - ok.
mov al,bh ;no - clip to lastpossible.
redisplay_00:
mov bl,al
mov bh,al
redisplay_1:
mov firstlastlimits,bx
;now truncate firstlimit if we can't get there.
mov al,firstlimit
cbw ;compute the number of display lines
sub al,w1.firstline ; desired before the cursor line.
cmp ax,linesbefore ;is it even possible to get there?
jb redisplay_2 ;yes - just do it.
mov ax,linesbefore ;no - truncate firstlimit to
add al,w1.firstline ; the largest possible.
mov firstlimit,al
redisplay_2:
;Now update row,col
call compute_cursor$
mov screen_column,dx
sub dx,w1.firstcolumn ;are we to the left of the screen?
jb redisplay_01 ;yes - must roll the screen right.
cmp dx,80 ;are we on the screen?
jb redisplay_02 ;yes - we don't have the roll left.
;roll the window to the left.
comment /
Eventually, we'll be smart about all this and really scroll the screen.
For now, we'll repaint the screen every time we roll.
jmp short redisplay_02
/
redisplay_01:
;roll the window to the right.
comment /
Eventually, we'll be smart about all this and really scroll the screen.
For now, we'll repaint the screen every time we roll.
/
add dx,w1.firstcolumn ;restore the cursor position.
mov bl,w1.firstline
mov al,w1.lastline
call trash_some_lines
and dl,not 7 ;back up to previous tab stop.
sub dx,40 ;put the cursor in middle of screen.
jae redisplay_03
mov dx,0 ;column is less than 40.
redisplay_03:
mov w1.firstcolumn,dx ;that is where we start redisplaying.......................
redisplay_02:
;now roll the screen up or down, as needed.
call roll_window_down
call roll_window_up
ret
redraw_trashed:
;redraw all changed lines if there are any to redraw.
redraw_trashed_4:
mov bl,w1.firstline
mov bh,0
mov dh,0 ;initially, we don't need to redraw any.
redraw_trashed_3:
mov dl,window[bx] ;get new window contents.
or dh,dl ;remember if we need to redraw any.
or dl,dl ;if positive, it's a line to be moved.
js redraw_trashed_5 ;if negative, skip it.
cmp dl,bl ;is the line already there?
je redraw_trashed_5 ;yes - skip it.
mov di,offset window ;is this row referred to?
mov cl,max_screen_line
inc cl
mov ch,0
mov al,bl
repne scasb ;scan for the row.
je redraw_trashed_5 ;yes - we can't move something here.
call move_line ;move dl to al.
mov dh,0 ;get the source line.
mov di,dx
mov al,inversed[di] ;transfer the inversed contents.
mov inversed[bx],al
mov window[bx],bl ;say that this line is where it is.
jmp redraw_trashed_4 ;restart search.
redraw_trashed_5:
inc bl
cmp bl,w1.lastline
jbe redraw_trashed_3
cmp inverse_flag,0 ;if we're inversing, we might need to redraw.
jne redraw_trashed_1
or dh,dh ;do we need to redraw any lines?
jns redraw_trashed_9 ;no.
redraw_trashed_1:
mov bl,w1.firstline
mov bh,0
mov cx,this_row ;get the row that the point is on.
sub cx,bx
call skip_to_line ;find the first line on the screen.
call redraw_anyway ;see if we need to redraw anyway.
redraw_trashed_7:
call redraw_compare ;remember if we're inversing here.
mov inversed[bx],al
cmp window[bx],0
jns redraw_trashed_a ;if negative, redraw it.
call redraw_line
mov window[bx],bl ;remember that this line is drawn.
redraw_trashed_a:
call remember_redrawn
inc bl
cmp bl,w1.lastline
jbe redraw_trashed_7
redraw_trashed_9:
mov inversing,0 ;say that we're not inversing.
ret
remember_redrawn:
;enter with si->text, bx=screen line.
;exit with si->next line.
call nextline
shl inversed[bx],1
shl inversed[bx],1
call redraw_compare
or inversed[bx],al
ret
redraw_anyway:
;preserve si,bx.
cmp inverse_flag,0
je redraw_anyway_1
push si
push bx
redraw_anyway_2:
call redraw_compare
push ax
call nextline ;see if this line contains the mark or point.
call redraw_compare
pop cx
mov ch,cl ;save a copy.
xor cl,al ;see if the bits changed.
test cl,1 ;is the point in this line?
jne redraw_anyway_yes ;yes - must redraw.
shl ch,1
shl ch,1
or al,ch ;make up the compare byte.
cmp al,inversed[bx] ;have they changed?
je redraw_anyway_no ;no - don't necessarily redraw.
redraw_anyway_yes:
mov window[bx],TRASHED ;say that this line is gone.
redraw_anyway_no:
inc bl
cmp bl,w1.lastline
jbe redraw_anyway_2
pop bx
pop si
redraw_anyway_1:
ret
redraw_compare:
;enter with si->text buffer.
;exit with al and 1 = 1 if si<point,
; al and 2 = 2 if si<mark.
cmp si,inverse_mark ;set cy if si is below inverse_mark (mark)
rcl al,1
cmp si,bottop ;set cy if si is below bottop (point)
rcl al,1
and al,3 ;get rid of other bits.
ret
skip_to_line:
;enter with cx=number of lines to move forward or backward.
;Note: positive values move toward top of file.
;return si -> beginning of desired line.
;don't destroy dx.
mov si,this_point ;get the point.
or cx,cx ;is cx negative?
js skip_to_line_4 ;yes - we have to move forward.
cmp [si-2].w,LINENEW ;if we're not at the beginning of
je skip_to_line_3 ; this line, backup to beginning.
call prevline
skip_to_line_3:
jcxz skip_to_line_2
skip_to_line_1:
call prevline
loopne skip_to_line_1
jne skip_to_line_2 ;did we hit the beginning?
inc cx ;yes - restore the count.
sub this_row,cx ;adjust this row.
jmp short skip_to_line_2
skip_to_line_4:
neg cx ;make cx into a positive count.
;cx is at least one.
skip_to_line_5:
call nextline
loopne skip_to_line_5
skip_to_line_2:
mov al,inverse_flag ;are we inversing?
cmp al,0
je skip_to_line_6 ;no.
push bx
push dx
push si
call get_mark ;the mark is in inverse_flag
mov inverse_mark,si ;remember where the inverse mark is.
pop si
pop dx
pop bx
skip_to_line_6:
ret
redraw_line:
;enter with si -> line to be redrawn, bl=row of line.
;paint from firstcolumn for 80 columns.
;this routine is intense.
;preserve cx, bx
call redraw_set
mov di,0 ;start at column zero.
mov dh,0
mov dl,bl
mov bl,-1 ;start without trailing blanks.
cmp si,botbot ;are we at bottom already?
je redraw_line_9_j_1 ;yes - clear to eol.
redraw_line_2:
call redraw_pointer
mov ax,[si]
cmp ax,LINENEW ;done with line?
je redraw_line_3 ;yes - exit.
inc si
cmp dh,79 ;at right hand column?
ja redraw_line_d ;yes - don't print.
cmp di,w1.firstcolumn ;before first column?
jb redraw_line_4 ;yes - just compute new column.
cmp al,' ' ;possible trailing blanks.
je redraw_line_a
cmp al,HT
jne redraw_line_b ;not trailing blanks - forget.
redraw_line_a:
cmp bl,-1 ;are we already remembering?
jne redraw_line_c ;yes - don't remember again.
mov bl,dh ;found a trailing blank character,
mov bp,si ; remember where it was.
jmp short redraw_line_c
redraw_line_b:
mov bl,-1 ;printable char - forget trailing blanks.
redraw_line_c:
call xy_char_put
jmp redraw_line_2
redraw_line_d:
cmp dh,80 ;did we just get there?
ja redraw_line_2 ;no.
dec dh
mov ax,8*256+MORE_CHAR ;yes - print the "more" symbol.
call xychrout
mov dh,81 ;say that we're in the next column.
jmp redraw_line_2
redraw_line_4:
inc di
cmp al,HT ;only tabs are special
jne redraw_line_2
mov ax,di
add ax,7 ;round up to next tab stop.
and al,not 7
mov di,ax
jmp redraw_line_2
redraw_line_9_j_1:
jmp redraw_line_9
redraw_line_3:
cmp showblanks,0 ;should we show blanks?
je redraw_line_8
cmp bl,-1 ;are there any trailing blanks?
je redraw_line_8 ;no.
mov dh,bl ;restore the column.
xchg si,bp ;save the current and restore the old.
dec si
call redraw_set
redraw_line_7:
call redraw_pointer
mov ax,[si] ;get the next char.
cmp ax,LINENEW
je redraw_line_e
cmp dh,79
ja redraw_line_e
inc si
cmp al,' ' ;it can only be a tab or a space.
je redraw_line_6 ;must be a space.
redraw_line_5:
mov ax,8*256+TRAIL_TAB ;output a trailing tab char.
call xychrout
inc dh
test dh,7 ;at a tab stop yet?
jne redraw_line_5 ;no.
jmp redraw_line_7
redraw_line_6: ;output a trailing blank char.
mov ax,8*256+TRAIL_BLANK
call xychrout
inc dh
jmp redraw_line_7
redraw_line_e:
mov si,bp ;restore the text pointer.
redraw_line_8:
cmp dh,80 ;put a newline symbol if there's room.
jae redraw_line_9
cmp inversing,0 ;only if we're inversing.
je redraw_line_9
mov ax,8*256+NEWLINE_CHAR ;newline symbol.
call xychrout
inc dh
redraw_line_9:
call clear_to_eol
mov bh,0 ;restore bx.
mov bl,dl
ret
redraw_pointer:
;adjust si from the top to the bottom if necessary, and adjust inversing.
cmp si,topbot ;at the point yet?
jne redraw_pointer_1 ;no.
mov si,bottop
cmp inverse_flag,0 ;are we inversing?
je redraw_pointer_1 ;no.
not inversing ;say that we've passed the point.
redraw_pointer_1:
cmp si,inverse_mark ;are we at the inverse mark?
jne redraw_pointer_2 ;yes - maybe inverse.
cmp inverse_flag,0 ;are we inversing?
je redraw_pointer_2 ;no.
not inversing ;say that we've passed the point.
redraw_pointer_2:
ret
redraw_set:
cmp inverse_flag,0 ;if we're not inversing, don't inverse.
je redraw_set_1
call redraw_compare
cmp si,inverse_mark ;are we exactly at the mark?
jne redraw_set_2 ;no - just check parity.
xor al,2 ;yes - flip the associated bit.
redraw_set_2:
mov inversing,0 ;say that we're not inversing.
or al,al ;look for 00,11 or 10,01
jpe redraw_set_1 ;go if not within point and mark.
not inversing ;say that we're inversing.
redraw_set_1:
ret
xy_char_put:
;put a char on the screen. Interpret tabs.
cmp al,HT
jne xy_char_put_1
xy_char_put_2:
mov al,' '
call xy_char_put_1
test dh,7
jnz xy_char_put_2
ret
xy_char_put_1:
mov ah,0
call xychrout
inc dh
xy_char_put_4:
ret
public prevline
prevline:
;retreat si to the previous line.
;return zr if si->beginning of file (and leave si alone)
;return nz otherwise.
;are we at the beginning of the file already?
cmp si,toptop
je prevline_beginning ;yes - exit.
;where are we in the file?
cmp si,topbot ;at, before or after the point?
jbe prevline_before
prevline_after:
dec si
cmp si,bottop ;have we reached the top of the bottom?
je prevline_at ;yes - drop down to prevline_before.
cmp [si-2].w,LINENEW ;at the beginning of a new line?
jne prevline_after ;no - keep looking.
dec si ;did we just find a non-real newline?
cmp si,bottop ;if we did, then si is now at bottop
je prevline_at ; and we need to keep searching.
inc si ;restore si and exit.
jmp short prevline_exit
prevline_at:
mov si,topbot ;start searching at the bottom
inc si ; of the top.
prevline_before:
dec si
cmp [si-2].w,LINENEW ;at the beginning of a new line?
jne prevline_before ;no - keep looking.
prevline_exit:
or si,si ;return nz
prevline_beginning:
ret
public nextline
nextline:
;advance si to the next line.
;return zr if si->end of file (and leave si alone)
;return nz otherwise.
cmp si,topbot
jne nextline_1
mov si,bottop
nextline_1:
cmp si,botbot
je nextline_2
cmp [si].w,LINENEW
je nextline_3
inc si
jmp nextline
nextline_3:
add si,2
or si,si
ret
nextline_2:
push ax
xor ax,ax
pop ax
ret
public compute_one
compute_one:
cmp al,HT
jne compute_one_1
and dl,0f8h
add dx,008h
ret
compute_one_1:
inc dx
ret
code ends
end